﻿using Ivory;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Schism.AI;
using Schism.Core;
using Schism.libs;
using Schism.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Schism.Actors
{
    public abstract class Actor : EntityBase, IPathableEntity, IViewableController
    {
        //Fields
        public Actor_InstructionState InstructionSetState { get; set; }
        public Actor_WarningState WarningState { get; set; }

        protected WaypointPath _WaypointPath;
        public event EventHandler<NoRouteFoundEventArgs> NoRouteFound;
                
        #region IPathableEntity
        public float ActorSpeed
        {
            get { return Speed; }
        }
        public bool IsControlled
        {
            get;
            set;
        }
        private float Speed { get; set; }
        public double Rotation
        {
            get;
            set;
        }
        #endregion
        
        //ctor
        public Actor(CellMap parent)
            : base(parent)
        {

        }

        //Methods
        protected abstract void RenderActorTexture(SpriteBatch batch, GameTime time);

        protected virtual void InstructionProcessor()
        {
            //I'll provide default state jumps, can be overridden later

            //if not overloaded, let jump to finished
            InstructionSetState = Actor_InstructionState.FINSIHED;
        }
        protected virtual void IdleNoInstructionStateProcessor() 
        {
            //I'll provide default state jumps, can be overridden later
        }
        protected virtual void IdleInstructionStateProcessor()
        {
            //I'll provide default state jumps, can be overridden later
            //Idle with instuctions - go to pathing mode
            InstructionSetState = Actor_InstructionState.PATHING;
            _WaypointPath.Start();
        }        
        protected virtual void FinishedStateProcessor()
        {
            //I'll provide default state jumps, can be overridden later
            //If not overriden, let just go to idle
            InstructionSetState = Actor_InstructionState.IDLE_NOINSTRUCTIONS;
        }
        
        public void Render(SpriteBatch batch, GameTime time)
        {
            //Draw the ActorWarningStateCircle
            batch.Draw(ResourceBank.Get<Texture2D>("actorstatecircle"), Position.WorldPosition - ObjectHolder.GameCamera.CameraTopLeft, ActorConverter.WaringStateToColor(WarningState));

            //Draw the next level actor
            RenderActorTexture(batch, time);

            //Draw the actor healthbar - if required (WarningState > Low)
            if (WarningState > Actor_WarningState.LOW)
            {
                //TODO:
            }
        }
        public void Solve(InputControl control, GameTime time)
        {
            switch (InstructionSetState)
            {
                case Actor_InstructionState.IDLE_NOINSTRUCTIONS:
                    {
                        IdleNoInstructionStateProcessor();
                        break;
                    }
                case Actor_InstructionState.IDLE_INSTRUCTIONS:
                    {
                        //Prepare to Go into pathing mode,
                        IdleInstructionStateProcessor();
                        break;
                    }
                case Actor_InstructionState.PATHING:
                    {
                        if (_WaypointPath == null)
                            InstructionSetState = Actor_InstructionState.INSTRUCTIONS;
                        else
                            _WaypointPath.UpdatePath(time);
                        break;
                    }
                case Actor_InstructionState.INSTRUCTIONS:
                    {
                        InstructionProcessor();
                        break;
                    }
                case Actor_InstructionState.FINSIHED:
                    {
                        FinishedStateProcessor();
                        break;
                    }
            }
            
        }
         
        public bool Initalize()
        {
            return true;
        }
        public bool Load()
        {
            InstructionSetState = Actor_InstructionState.IDLE_NOINSTRUCTIONS;
            WarningState = Actor_WarningState.LOW;
            return true;
        }
                
        public void PathTo(DungeonPos position)
        {
            Waypoint[] path = AStarPathFinder.FindPathBetween(Position, position, ParentMap).ToArray();
            if(path == null)
            {
                if(NoRouteFound != null)
                    NoRouteFound(this, new NoRouteFoundEventArgs(position));

                return;
            }

            _WaypointPath = new WaypointPath(this, path);
            //When we finish pathing, go to instructions
            _WaypointPath.PathFinished += (S, e) => { InstructionSetState = Actor_InstructionState.INSTRUCTIONS; };
        }
    }
}
